// 防抖
export const funDebounce = <T extends (...args: any[]) => any>(
  func: T,
  param1?: number | boolean,
  param2?: boolean
): ((...args: Parameters<T>) => ReturnType<T> | void) => {
  if (typeof func !== "function")
    throw new TypeError("func must be a function!");

  // 参数处理
  const wait = typeof param1 === "number" ? param1 : 500;
  const immediate =
    typeof param2 === "boolean"
      ? param2
      : typeof param1 === "boolean"
      ? param1
      : true;

  let timer: ReturnType<typeof setTimeout> | null = null;
  let result: ReturnType<T> | void;

  return (...args: Parameters<T>) => {
    const callNow = !timer && immediate;

    if (timer) clearTimeout(timer);

    timer = setTimeout(() => {
      timer = null;
      if (!immediate) result = func(...args);
    }, wait);

    if (callNow) result = func(...args);
    return result;
  };
};

// 节流
export const funThrottle = <T extends (...args: any[]) => any>(
  func: T,
  wait: number = 500
): ((...args: Parameters<T>) => ReturnType<T> | void) => {
  if (typeof func !== "function")
    throw new TypeError("func must be a function!");

  let timer: ReturnType<typeof setTimeout> | null = null;
  let previous = 0;
  let result: ReturnType<T> | void;

  return (...args: Parameters<T>) => {
    const now = Date.now();
    const remaining = wait - (now - previous);

    if (remaining <= 0) {
      if (timer) {
        clearTimeout(timer);
        timer = null;
      }
      previous = now;
      result = func(...args);
      return result;
    }

    if (!timer) {
      timer = setTimeout(() => {
        timer = null;
        previous = Date.now();
        result = func(...args);
      }, remaining);
    }

    return result;
  };
};

interface Toast {
  title: string;
  icon?: "success" | "loading" | "none";
  image?: string;
  duration?: number;
  mask?: boolean;
  position?: "top" | "center" | "bottom";
  success?: () => void;
  fail?: () => void;
  complete?: () => void;
}

export const Toast = (params: string | Toast) => {
  typeof params === "string"
    ? uni.showToast({
        title: params,
        icon: "none",
      })
    : uni.showToast(params);
};
